package net.borlis.configuration.context.tt;

import net.borlis.configuration.common.ConfigurationInitError;
import net.borlis.configuration.common.DatabaseDriver;
import net.borlis.configuration.common.StandardConfiguration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.tree.ConfigurationNode;

import javax.annotation.PostConstruct;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author alex@borlis.net
 */
@Dependent //todo:: check the scope deep!!! #sprint16 #maverick
public class ContextFileConfiguration extends StandardConfiguration {

//    @Inject
    private Logger logger;
    // -=-=-=-
    private XMLConfiguration configuration;

//    @Inject @ContextFile
    private final ConfigurationFileName configurationFileName;

    @Inject
    public ContextFileConfiguration(Logger logger, ConfigurationFileName configurationFileName) {
        this.logger = logger;
        this.configurationFileName = configurationFileName;
        init(); // todo:: check the @PostConstruct method - it does not start, it crashes few tests!!! #sprint16 #maverick
    }

    /**
     * Init the configuration with the provided configuration file.
     */
    @PostConstruct
    private void init() {
        try {
            logger.info("configuration loading started");
            logger.info("configuration file name = " + configurationFileName.getFileName());
            // -=-=-
            configuration = new XMLConfiguration();
            configuration.setFileName(configurationFileName.getFileName());
            // -=-=-
            configuration.setValidating(false);
            configuration.load();
            // -=-=-
            /*
            <Resource factory="net.borlis.configuration.context.tt.ContextFileConfiguration"
              schemaVersion="test_sample"
              databaseDriver="com.mysql.jdbc.Driver"
              databaseServer="10.5.52.113"
              databasePort="3306"
              databaseUser="dynamix-test"
              databasePassword="N62%N&amp;iq5E"
              databaseAutoUpdate="true"
              encryptionServiceLogin=
              encryptionServicePassword=
              encryptionServiceURL=
              clientKey=
            />
             */

            logger.info("configuration = " + configuration);
            // -=-=-
            initJdbc();
            logger.info("configuration loading finished");
        } catch (ConfigurationException|NullPointerException cex) {
            logger.log(Level.SEVERE, "cannot load the configuration", cex);
            throw new ConfigurationInitError(cex);
        }
    }

    private List<ConfigurationNode> getTTResource() {
        final String factoryName = "net.borlis.configuration.context.tt.ContextFileConfiguration";
        List<HierarchicalConfiguration> fields = configuration.configurationsAt("TTResource");
        for (HierarchicalConfiguration field : fields) {
            if (factoryName.equals(field.getRoot().getAttributes("factory").get(0).getValue().toString())) {
                return field.getRoot().getAttributes();
            }
        }
        throw new IllegalStateException("there is no tt resource");
    }

    public void initJdbc() {
        for (ConfigurationNode node : getTTResource()) {
            logger.info(node.getName() + "=" + node.getValue());
            if ("schemaVersion".equals(node.getName())) {
                setSchemaVersion(node.getValue().toString());
            }
            if ("databaseDriver".equals(node.getName())) {
                setDriverName(node.getValue().toString());
            }
            if ("databaseServer".equals(node.getName())) {
                setServer(node.getValue().toString());
            }
            if ("databasePort".equals(node.getName())) {
                setPort(node.getValue().toString());
            }
            if ("databaseUser".equals(node.getName())) {
                setJdbcUser(node.getValue().toString());
            }
            if ("databasePassword".equals(node.getName())) {
                setJdbcPassword(node.getValue().toString());
            }
            if ("databaseAutoUpdate".equals(node.getName())) {
                setAutoUpdate(Boolean.valueOf(node.getValue().toString()));
            }
            if ("encryptionServiceLogin".equals(node.getName())) {
                setEncryptionServiceLogin(node.getValue().toString());
            }
            if ("encryptionServicePassword".equals(node.getName())) {
                setEncryptionServicePassword(node.getValue().toString());
            }
            if ("encryptionServiceURL".equals(node.getName())) {
                setEncryptionServiceURL(node.getValue().toString());
            }
            if ("clientKey".equals(node.getName())) {
                setClientKey(node.getValue().toString());
            }
        }
        //todo:: add the validation!!!
        final String urlPrefix;
        if (DatabaseDriver.MYSQL_DRIVER.getDriverName().equals(getDriverName())) {
            urlPrefix = "jdbc:mysql://";
        } else {
            throw new IllegalStateException("unknown db driver");
        }
        setJdbcUrl(urlPrefix + getServer() + ":" + getPort() + "/" + getSchemaVersion() + "_");
    }

    public XMLConfiguration getConfiguration() {
        return configuration;
    }

}
